package com.feature50.makeover.utils;

import com.feature50.makeover.utils.ReflectionUtils;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;

public class ArrayUtils {
    /**
     * As a convenience, this version accepts any object. As a bonus, it
     * supports any indexed type. I'm not sure where this method belongs.
     *
     * @param array
     */
    public static boolean nullOrEmpty(Object array) {
        if (array == null)
            return true;

        if (ReflectionUtils.isIndexedType(array)) {
            Object[] ar = (Object[]) ReflectionUtils.getIndexedType(array, Object[].class);
            return nullOrEmpty(ar);
        }

        return false;
    }

    public static boolean nullOrEmpty(Object[] array) {
        return ((array == null) || (array.length == 0));
    }

    @SuppressWarnings("unchecked")
    public static <T> T[] removeIndex(T[] array, int index) {

        T[] newArray = (T[]) Array.newInstance(array.getClass().getComponentType(), array.length - 1);

        if (index > 0) {
            System.arraycopy(array, 0, newArray, 0, index);
        }

        if (index < array.length - 1) {
            System.arraycopy(array, index + 1, newArray, index, array.length - index - 1);
        }

        return newArray;
    }

    public static <T> boolean contains(T[] array, T object) {
        return indexOf(array, object) != -1;
    }

    public static <T> int indexOf(T[] array, T object) {
        for (int i = 0; i < array.length; i++) {
            Object o = array[i];
            if (o == object)
                return i;
        }
        return -1;
    }

    public static float[] toPrimitive(Float[] f) {
        if (f == null) return null;
        float[] p = new float[f.length];
        for (int i = 0; i < f.length; i++) p[i] = f[i];
        return p;
    }

    /**
     * Retrieves the object at the specified index in the passed Collection or Array.
     *
     * @param collectionOrArray
     * @param index
     * @return
     */
    public static Object get(Object collectionOrArray, int index) {
        if (collectionOrArray instanceof Collection) {
            return get((Collection) collectionOrArray, index);
        } else if (collectionOrArray.getClass().isArray()) {
            return ((Object[]) collectionOrArray)[index];
        } else {
            throw new IllegalArgumentException(String.format("Don't know how to treat object of type '%1$s' as an array", collectionOrArray.getClass()));
        }
    }

    private static Object get(Collection collection, int index) {
        int counter = 0;
        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
            Object o = iterator.next();
            if (counter++ == index) return o;
        }
        throw new IndexOutOfBoundsException(String.format("Index %1$d is out of bounds of the passed collection of size %2$d", index, counter));
    }
}
